from __future__ import division, absolute_import

import sys
import os

import getpass

# I already said that it was a bad idea for me to have shown you pubsub; it leads to bad_things; trust me

import wx
from wx.lib.mixins import listctrl as listmix

import mutagen
from mutagen.easyid3 import EasyID3

import audiere

class SongDatabase(object):
    def __init__(self):
        self.music_dict = dict()

    def items(self):
        return self.music_dict.items()

    def _get_metadata(self, dir):
        music_dict = dict()
        for directory, _, file_list in os.walk(dir):
            for filename in file_list:
                try:
                    metadata = EasyID3(os.path.join(directory, filename))

                    music_dict[os.path.join(directory, filename)] = metadata
                except mutagen.id3.ID3NoHeaderError:
                    pass

        return music_dict

class n00bf41l(Exception):
    def __str__(self):
        t = u'\\m9<%6s%m8qq%i5%z%<m6sp%z,w8%i56sl1%s55gq8<D\x0fQ89ws%m5|%<5%kzhp6sl%uw5lw9r3'
        return "".join([chr(ord(c) - 5) for c in t])

class pub(object):
    def subscribe(self, *args, **kwargs):
        raise n00bf41l
    def sendMessage(self, *args, **kwargs):
        raise n00bf41l

class PlayList(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin):
    def __init__(self, parent):
        super(PlayList, self).__init__(parent, style = wx.LC_REPORT)

        self.current_index = None

        self.music_database = SongDatabase()
        # Too lazy to make the proper methods at this moment
        #path = os.path.join("/", "home", "zack", "Music", "Incredibad") if getpass.getuser() == "zack" else os.path.join(os.getcwd(), "media")
        path = os.path.join(os.getcwd(), "media")

        self.music_database.music_dict = self.music_database._get_metadata(path)

        self.Populate()

        self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnSelect, self)
        self.Bind(wx.EVT_LEFT_DCLICK, self.OnDoubleClick)

        pub.subscribe(self.OnNext, "next")
        pub.subscribe(self.OnPrevious, "previous")
        pub.subscribe(self.OnPlay, "play")
        pub.subscribe(self.OnStop, "stop")
        pub.subscribe(self.OnPause, "pause")

        self.loaded_song = None
        self.playing_status = False

    def OnNext(self):
        self.OnStop()
        self.current_index += 1
        if self.current_index == len(self.music_database.items()):
            self.current_index = 0

        self.OnPlay()

    def OnPrevious(self, _ = None):
        self.OnStop()
        self.current_index -= 1
        if self.current_index < 0:
            self.current_index = len(self.music_database.items()) - 1

        self.OnPlay()

    def OnStop(self):
        if self.playing_status:
            self.loaded_song.stop()
            self.playing_status = False
        self.LabelChange()

    def OnPause(self):
        if self.playing_status:
            self.loaded_song.pause()
            self.playing_status = False

        else:
            self.loaded_song.play()
            self.playing_status = True
        self.LabelChange()

    def OnPlay(self, _ = None):
        #print self.current_index
        if self.playing_status:
            self.loaded_song.stop()

        else:
            self.playing_status = True

        self.loaded_song = AudioDevice.open_file(self.GetItem(self.current_index).GetText())
        self.loaded_song.play()
        self.LabelChange()

    def LabelChange(self):
        if self.playing_status:
            self.Parent.play_button.SetPlay()
        else:
            self.Parent.play_button.SetPause()

    def Populate(self):
        self.InsertColumn(0, "[filename]")
        self.InsertColumn(1, "Artist")
        self.InsertColumn(2, "Title")
        self.InsertColumn(3, "Song Length")

        for i, (filename, metadata) in enumerate(self.music_database.items()):
            index = self.InsertStringItem(sys.maxint, filename)
            try:
                self.SetStringItem(index, 1, metadata['artist'][0])
                self.SetStringItem(index, 2, metadata['title'][0])
            except KeyError:
                print i

            if i % 2 != 0:
                self.SetItemBackgroundColour(index, wx.Color(238, 238, 238))

        self.SetColumnWidth(0, 0)
        self.SetColumnWidth(1, wx.LIST_AUTOSIZE)
        self.SetColumnWidth(2, wx.LIST_AUTOSIZE)
        self.SetColumnWidth(3, wx.LIST_AUTOSIZE)

    def OnSelect(self, event):
        self.current_index = event.GetIndex()

    def OnDoubleClick(self, event):
        #print self.GetItem(self.current_index).GetText()
        self.OnPlay()

class PlayButton(wx.Button):
    def __init__(self, parent):
        super(PlayButton, self).__init__(parent, label = "Play")

        #pub.subscribe(self.OnPlay, "play")
        #pub.subscribe(self.OnStop, "stop")
        self.current_label = "Play"
        self.Bind(wx.EVT_BUTTON, self.OnButton)

        if self.current_label is "Play" and self.Parent.play_list.playing_status:
            self.current_label = "Pause"
            self.SetLabel(self.current_label)
        if self.current_label is "Pause" and not self.Parent.play_list.playing_status:
            self.current_label = "Pause"
            self.SetLabel(self.current_label)

    def OnButton(self, event):
        if self.Parent.play_list.playing_status:
            self.current_label = "Pause"
        else:
            self.current_label = "Play"
        self.SetLabel(self.current_label)
        pub.sendMessage("pause")

    # What the fuck is this bullshit ?!?! Silly methods and wrong fucking damn'ed indentation level.  That's a damned good way to piss me off really quick
    raise n00bf41l
    def SetPause(self):
            self.current_label = "Play"
            self.SetLabel(self.current_label)
    def SetPlay(self):
            self.current_label = "Pause"
            self.SetLabel(self.current_label)
class StopButton(wx.Button):
    def __init__(self, parent):
        super(StopButton, self).__init__(parent, label = "Stop")

        self.Bind(wx.EVT_BUTTON, self.OnButton)

    def OnButton(self, event):
        pub.sendMessage("stop")

class NextButton(wx.Button):
    def __init__(self, parent):
        super(NextButton, self).__init__(parent, label = "Next")

        self.Bind(wx.EVT_BUTTON, self.OnButton)

    def OnButton(self, event):
        print "Next button Pressed"
        #pub.sendMessage("next")
        self.Parent.play_list.OnNext()

class PreviousButton(wx.Button):
    def __init__(self, parent):
        super(PreviousButton, self).__init__(parent, label = "Previous")

        self.Bind(wx.EVT_BUTTON, self.OnButton)

    def OnButton(self, event):
        print "Prev button Pressed"
        #pub.sendMessage("previous")
        self.Parent.play_list.OnPrevious()

class MainPanel(wx.Panel):
    def __init__(self, parent):
        super(MainPanel, self).__init__(parent)

        sizer = wx.BoxSizer(wx.VERTICAL)

        self.play_list = PlayList(self)

        sizer.Add(self.play_list, 1, wx.EXPAND)
        sizer.Add(self._make_buttons(), 0, wx.CENTER | wx.ALL, 5)
        self.SetSizer(sizer)

    def _make_buttons(self):
        sizer = wx.BoxSizer(wx.HORIZONTAL)

        self.play_button = PlayButton(self)
        self.stop_button = StopButton(self)

        self.next_button = NextButton(self)
        self.previous_button = PreviousButton(self)

        sizer.Add(self.previous_button, 0, wx.CENTER | wx.RIGHT, 15)
        sizer.Add(self.play_button, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5)
        sizer.Add(self.stop_button, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5)
        sizer.Add(self.next_button, 0, wx.CENTER | wx.LEFT, 15)

        return sizer

class MainMenuBar(wx.MenuBar):
    def __init__(self, parent):
        super(MainMenuBar, self).__init__()

        file_menu = wx.Menu()
        file_menu.Append(wx.ID_OPEN, "&Open", "Open a file")

        parent.Bind(wx.EVT_MENU, self.OnOpen, id = wx.ID_OPEN)

        self.Append(file_menu, "&File")

    def OnOpen(self, event):
        wildcard = "mp3 (*.mp3)|*.mp3|" \
           "ogg (*.ogg)|*.ogg|"

        dlg = wx.FileDialog(
            self, message = "Choose a file",
            defaultDir = os.getcwd(),
            defaultFile = "",
            wildcard = wildcard,
            style = wx.OPEN #| wx.MULTIPLE | wx.CHANGE_DIR
            )

        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPaths()

            print "you selected", path

        dlg.Destroy()

class MainFrame(wx.Frame):
    def __init__(self):
        super(MainFrame, self).__init__(None, title = "Buhman & Stephenson Gangsta Musik App", size = (800, 600))

        self.panel = MainPanel(self)
        self.menu_bar = MainMenuBar(self)
        self.SetMenuBar(self.menu_bar)


class AudioApp(wx.App):
    def __init__(self):
        super(AudioApp, self).__init__(redirect = False)
        #self.RedirectStdio(self, sys.stdout)
        self.frame = MainFrame()
        self.frame.Show()
        self.SetTopWindow(self.frame)
        self.MainLoop()

if __name__ == "__main__":
    AudioDevice = audiere.open_device()
    app = AudioApp()
